{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 1]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a=[0,1]\n",
    "print(np.concatenate((a,[1]),axis=0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pose is x: 0.550000, y:0.600000, phi:0\n"
     ]
    }
   ],
   "source": [
    "import utils\n",
    "from position import *\n",
    "\n",
    "print(utils.trans_relative_co(pose(0,0,90), pose(-0.6,0.55,0)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "z=2\n",
    "print(z if z<1 else -(1-z))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-07-15 17:27:01,021 ERROR action.py:355 Robot is already performing 1 action(s) action_id:3, state:action_started, percent:0, x:0.3, y:0.2, z:5, xy_speed:0.5, z_speed:30\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "moving times: 1 with direction of 1\n",
      "moving times: 2 with direction of -1\n"
     ]
    },
    {
     "ename": "Exception",
     "evalue": "Robot is already performing 1 action(s) action_id:3, state:action_started, percent:0, x:0.3, y:0.2, z:5, xy_speed:0.5, z_speed:30",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mException\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[2], line 15\u001b[0m\n\u001b[0;32m     13\u001b[0m n\u001b[39m+\u001b[39m\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m\n\u001b[0;32m     14\u001b[0m \u001b[39mprint\u001b[39m(\u001b[39m'\u001b[39m\u001b[39mmoving times: \u001b[39m\u001b[39m%d\u001b[39;00m\u001b[39m with direction of \u001b[39m\u001b[39m%a\u001b[39;00m\u001b[39m'\u001b[39m \u001b[39m%\u001b[39m (n,a))\n\u001b[1;32m---> 15\u001b[0m ep_chassis\u001b[39m.\u001b[39;49mmove(x\u001b[39m=\u001b[39;49m\u001b[39m0.3\u001b[39;49m\u001b[39m*\u001b[39;49ma, y\u001b[39m=\u001b[39;49m\u001b[39m0.2\u001b[39;49m\u001b[39m*\u001b[39;49ma, z\u001b[39m=\u001b[39;49m\u001b[39m5\u001b[39;49m\u001b[39m*\u001b[39;49ma)\n\u001b[0;32m     16\u001b[0m time\u001b[39m.\u001b[39msleep(\u001b[39m0.1\u001b[39m)\n\u001b[0;32m     17\u001b[0m a\u001b[39m=\u001b[39m\u001b[39m-\u001b[39ma\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\chassis.py:488\u001b[0m, in \u001b[0;36mChassis.move\u001b[1;34m(self, x, y, z, xy_speed, z_speed)\u001b[0m\n\u001b[0;32m    478\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\" 控制底盘运动当指定位置，坐标轴原点为当前位置\u001b[39;00m\n\u001b[0;32m    479\u001b[0m \n\u001b[0;32m    480\u001b[0m \u001b[39m:param x: float: [-5,5]，x轴向运动距离，单位 m\u001b[39;00m\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    485\u001b[0m \u001b[39m:return: 返回action对象\u001b[39;00m\n\u001b[0;32m    486\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[0;32m    487\u001b[0m action \u001b[39m=\u001b[39m ChassisMoveAction(x, y, z, xy_speed, z_speed)\n\u001b[1;32m--> 488\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_action_dispatcher\u001b[39m.\u001b[39;49msend_action(action)\n\u001b[0;32m    489\u001b[0m \u001b[39mreturn\u001b[39;00m action\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\action.py:356\u001b[0m, in \u001b[0;36mActionDispatcher.send_action\u001b[1;34m(self, action, action_type)\u001b[0m\n\u001b[0;32m    354\u001b[0m             action \u001b[39m=\u001b[39m \u001b[39mlist\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress\u001b[39m.\u001b[39mvalues())[\u001b[39m0\u001b[39m]\n\u001b[0;32m    355\u001b[0m             logger\u001b[39m.\u001b[39merror(\u001b[39m\"\u001b[39m\u001b[39mRobot is already performing \u001b[39m\u001b[39m{0}\u001b[39;00m\u001b[39m action(s) \u001b[39m\u001b[39m{1}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\u001b[39mlen\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress), action))\n\u001b[1;32m--> 356\u001b[0m             \u001b[39mraise\u001b[39;00m \u001b[39mException\u001b[39;00m(\u001b[39m\"\u001b[39m\u001b[39mRobot is already performing \u001b[39m\u001b[39m{0}\u001b[39;00m\u001b[39m action(s) \u001b[39m\u001b[39m{1}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\n\u001b[0;32m    357\u001b[0m                 \u001b[39mlen\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress), action))\n\u001b[0;32m    358\u001b[0m     \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress_mutex\u001b[39m.\u001b[39mrelease()\n\u001b[0;32m    359\u001b[0m \u001b[39mif\u001b[39;00m action\u001b[39m.\u001b[39mis_running:\n",
      "\u001b[1;31mException\u001b[0m: Robot is already performing 1 action(s) action_id:3, state:action_started, percent:0, x:0.3, y:0.2, z:5, xy_speed:0.5, z_speed:30"
     ]
    }
   ],
   "source": [
    "import time\n",
    "from robomaster import robot\n",
    "\n",
    "ep_robot = robot.Robot()\n",
    "ep_robot.initialize(conn_type=\"sta\")\n",
    "\n",
    "ep_chassis = ep_robot.chassis\n",
    "ep_gripper=ep_robot.gripper\n",
    "speed=50\n",
    "a=1\n",
    "n=0\n",
    "for i in range(10):\n",
    "    n+=1\n",
    "    print('moving times: %d with direction of %a' % (n,a))\n",
    "    ep_chassis.move(x=0.3*a, y=0.2*a, z=5*a,timeout=1)\n",
    "    time.sleep(0.1)\n",
    "    a=-a\n",
    "# time.sleep(3)\n",
    "# ep_chassis.drive_wheels(w1=speed, w2=0, w3=0, w4=0)\n",
    "# time.sleep(1)\n",
    "# ep_chassis.drive_wheels(w1=0, w2=speed, w3=0, w4=0)\n",
    "# time.sleep(1)\n",
    "# ep_chassis.move(0, 0, 15, 1.8).wait_for_completed()\n",
    "# ep_gripper.open(power=100)\n",
    "# time.sleep(2)\n",
    "# ep_gripper.close(power=50)\n",
    "# time.sleep(2)\n",
    "ep_robot.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-06-22 23:05:49,054 ERROR action.py:355 Robot is already performing 1 action(s) action_id:2, state:action_running, percent:45, x:189, y:-56, z:0\n"
     ]
    },
    {
     "ename": "Exception",
     "evalue": "Robot is already performing 1 action(s) action_id:2, state:action_running, percent:45, x:189, y:-56, z:0",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mException\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[3], line 21\u001b[0m\n\u001b[0;32m     19\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[0;32m     20\u001b[0m     ep_gripper\u001b[39m.\u001b[39mopen(power\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m)\n\u001b[1;32m---> 21\u001b[0m ep_arm\u001b[39m.\u001b[39;49mmove(x\u001b[39m=\u001b[39;49m\u001b[39m5\u001b[39;49m\u001b[39m*\u001b[39;49ma, y\u001b[39m=\u001b[39;49m\u001b[39m10\u001b[39;49m\u001b[39m*\u001b[39;49ma)\n\u001b[0;32m     22\u001b[0m time\u001b[39m.\u001b[39msleep(\u001b[39m0.5\u001b[39m)\n\u001b[0;32m     23\u001b[0m a\u001b[39m=\u001b[39m\u001b[39m-\u001b[39ma\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\robotic_arm.py:120\u001b[0m, in \u001b[0;36mRoboticArm.move\u001b[1;34m(self, x, y)\u001b[0m\n\u001b[0;32m    113\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\" 机械臂相对位置移动\u001b[39;00m\n\u001b[0;32m    114\u001b[0m \n\u001b[0;32m    115\u001b[0m \u001b[39m:param x: float, x轴运动距离，向前移动为正方向，单位 mm\u001b[39;00m\n\u001b[0;32m    116\u001b[0m \u001b[39m:param y: float, y轴运动距离，向上移动为正方向，单位 mm\u001b[39;00m\n\u001b[0;32m    117\u001b[0m \u001b[39m:return: action对象\u001b[39;00m\n\u001b[0;32m    118\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[0;32m    119\u001b[0m action \u001b[39m=\u001b[39m RoboticArmMoveAction(x, y, z\u001b[39m=\u001b[39m\u001b[39m0\u001b[39m, mode\u001b[39m=\u001b[39m\u001b[39m0\u001b[39m)\n\u001b[1;32m--> 120\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_action_dispatcher\u001b[39m.\u001b[39;49msend_action(action)\n\u001b[0;32m    121\u001b[0m \u001b[39mreturn\u001b[39;00m action\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\action.py:356\u001b[0m, in \u001b[0;36mActionDispatcher.send_action\u001b[1;34m(self, action, action_type)\u001b[0m\n\u001b[0;32m    354\u001b[0m             action \u001b[39m=\u001b[39m \u001b[39mlist\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress\u001b[39m.\u001b[39mvalues())[\u001b[39m0\u001b[39m]\n\u001b[0;32m    355\u001b[0m             logger\u001b[39m.\u001b[39merror(\u001b[39m\"\u001b[39m\u001b[39mRobot is already performing \u001b[39m\u001b[39m{0}\u001b[39;00m\u001b[39m action(s) \u001b[39m\u001b[39m{1}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\u001b[39mlen\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress), action))\n\u001b[1;32m--> 356\u001b[0m             \u001b[39mraise\u001b[39;00m \u001b[39mException\u001b[39;00m(\u001b[39m\"\u001b[39m\u001b[39mRobot is already performing \u001b[39m\u001b[39m{0}\u001b[39;00m\u001b[39m action(s) \u001b[39m\u001b[39m{1}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(\n\u001b[0;32m    357\u001b[0m                 \u001b[39mlen\u001b[39m(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress), action))\n\u001b[0;32m    358\u001b[0m     \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_in_progress_mutex\u001b[39m.\u001b[39mrelease()\n\u001b[0;32m    359\u001b[0m \u001b[39mif\u001b[39;00m action\u001b[39m.\u001b[39mis_running:\n",
      "\u001b[1;31mException\u001b[0m: Robot is already performing 1 action(s) action_id:2, state:action_running, percent:45, x:189, y:-56, z:0"
     ]
    }
   ],
   "source": [
    "import time\n",
    "from robomaster import robot\n",
    "\n",
    "ep_robot = robot.Robot()\n",
    "ep_robot.initialize(conn_type=\"sta\")\n",
    "\n",
    "ep_chassis = ep_robot.chassis\n",
    "ep_gripper=ep_robot.gripper\n",
    "ep_arm = ep_robot.robotic_arm\n",
    "t1=time.time()\n",
    "# ep_arm.move(x=0, y=-15).wait_for_completed()\n",
    "\n",
    "t2=time.time()\n",
    "a=1\n",
    "for i in range(10):\n",
    "    # ep_chassis.drive_speed(0.1*a,0,0)\n",
    "    if a > 0:\n",
    "        ep_gripper.close(power=50)\n",
    "    else:\n",
    "        ep_gripper.open(power=50)\n",
    "    ep_arm.move(x=5*a, y=10*a)\n",
    "    time.sleep(0.5)\n",
    "    a=-a\n",
    "# ep_gripper.pause()\n",
    "# ep_chassis.pause()\n",
    "# ep_arm.move(x=0, y=-10).wait_for_completed()\n",
    "t3=time.time()\n",
    "\n",
    "ep_robot.close()\n",
    "print(t2-t1)\n",
    "print(t3-t2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "from robomaster import robot\n",
    "\n",
    "ep_robot = robot.Robot()\n",
    "ep_robot.initialize(conn_type=\"sta\")\n",
    "\n",
    "ep_chassis = ep_robot.chassis\n",
    "ep_gripper=ep_robot.gripper\n",
    "ep_arm = ep_robot.robotic_arm\n",
    "\n",
    "ep_chassis.drive_wheels(-50,-50,0,0,timeout=5)\n",
    "ep_arm.move(0,-20)\n",
    "time.sleep(1)\n",
    "\n",
    "# ep_gripper.close(power=100)\n",
    "# time.sleep(1)\n",
    "# ep_arm.move(x=-25, y=0)\n",
    "ep_robot.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "import msvcrt\n",
    "\n",
    "print(\"press SPACE to enter the serial number\")\n",
    "n=0\n",
    "while not msvcrt.kbhit() or msvcrt.getch() == \" \":\n",
    "    # do something else\n",
    "    n+=1\n",
    "    print(n)\n",
    "    time.sleep(0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "from robomaster import robot\n",
    "\n",
    "ep_robot = robot.Robot()\n",
    "ep_robot.initialize(conn_type=\"sta\")\n",
    "\n",
    "ep_chassis = ep_robot.chassis\n",
    "ep_gripper=ep_robot.gripper\n",
    "ep_arm = ep_robot.robotic_arm\n",
    "speed=50\n",
    "ep_chassis.drive_wheels(w1=-speed, w2=-speed, w3=-speed, w4=-speed)\n",
    "time.sleep(1)\n",
    "\n",
    "ep_robot.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "ename": "UnicodeDecodeError",
     "evalue": "'utf-8' codec can't decode byte 0xe7 in position 1: invalid continuation byte",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mUnicodeDecodeError\u001b[0m                        Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[26], line 23\u001b[0m\n\u001b[0;32m     19\u001b[0m     ep_arm\u001b[39m.\u001b[39munsub_position()\n\u001b[0;32m     22\u001b[0m multi_robots \u001b[39m=\u001b[39m multi_robot\u001b[39m.\u001b[39mMultiEP()\n\u001b[1;32m---> 23\u001b[0m multi_robots\u001b[39m.\u001b[39;49minitialize()\n\u001b[0;32m     25\u001b[0m number \u001b[39m=\u001b[39m multi_robots\u001b[39m.\u001b[39mnumber_id_by_sn([\u001b[39m2\u001b[39m, robots_sn_list[\u001b[39m1\u001b[39m]])\n\u001b[0;32m     26\u001b[0m g_red \u001b[39m=\u001b[39m multi_robots\u001b[39m.\u001b[39mbuild_group([\u001b[39m2\u001b[39m])\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\multi_robomaster\\multi_robot.py:171\u001b[0m, in \u001b[0;36mMultiEP.initialize\u001b[1;34m(self, proto_type)\u001b[0m\n\u001b[0;32m    165\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39minitialize\u001b[39m(\u001b[39mself\u001b[39m, proto_type\u001b[39m=\u001b[39mconfig\u001b[39m.\u001b[39mDEFAULT_PROTO_TYPE):\n\u001b[0;32m    166\u001b[0m \u001b[39m    \u001b[39m\u001b[39m\"\"\"scan all robots and init its\u001b[39;00m\n\u001b[0;32m    167\u001b[0m \n\u001b[0;32m    168\u001b[0m \u001b[39m    :param num:\u001b[39;00m\n\u001b[0;32m    169\u001b[0m \u001b[39m    :return:\u001b[39;00m\n\u001b[0;32m    170\u001b[0m \u001b[39m    \"\"\"\u001b[39;00m\n\u001b[1;32m--> 171\u001b[0m     \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_robots_list \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_scan_multi_robot(proto_type)\n\u001b[0;32m    172\u001b[0m     \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_robots_list:\n\u001b[0;32m    173\u001b[0m         logger\u001b[39m.\u001b[39merror(\u001b[39m\"\u001b[39m\u001b[39mMultiRobotBase: initialize. No robot was found!\u001b[39m\u001b[39m\"\u001b[39m)\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\multi_robomaster\\multi_robot.py:185\u001b[0m, in \u001b[0;36mMultiEP._scan_multi_robot\u001b[1;34m(self, proto_type)\u001b[0m\n\u001b[0;32m    180\u001b[0m \u001b[39m\u001b[39m\u001b[39m\"\"\" Automatic scanning of robots in the network\u001b[39;00m\n\u001b[0;32m    181\u001b[0m \n\u001b[0;32m    182\u001b[0m \u001b[39m:return:\u001b[39;00m\n\u001b[0;32m    183\u001b[0m \u001b[39m\"\"\"\u001b[39;00m\n\u001b[0;32m    184\u001b[0m robot_list \u001b[39m=\u001b[39m []\n\u001b[1;32m--> 185\u001b[0m ip_list \u001b[39m=\u001b[39m conn\u001b[39m.\u001b[39;49mscan_robot_ip_list(\u001b[39m10\u001b[39;49m)\n\u001b[0;32m    186\u001b[0m \u001b[39mfor\u001b[39;00m i, ip \u001b[39min\u001b[39;00m \u001b[39menumerate\u001b[39m(ip_list):\n\u001b[0;32m    187\u001b[0m     sdk_conn \u001b[39m=\u001b[39m conn\u001b[39m.\u001b[39mSdkConnection()\n",
      "File \u001b[1;32mc:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\conn.py:136\u001b[0m, in \u001b[0;36mscan_robot_ip_list\u001b[1;34m(timeout)\u001b[0m\n\u001b[0;32m    134\u001b[0m     logger\u001b[39m.\u001b[39mwarning(\u001b[39m\"\u001b[39m\u001b[39mscan_robot_ip_list: socket recv, \u001b[39m\u001b[39m{0}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(e))\n\u001b[0;32m    135\u001b[0m     \u001b[39mcontinue\u001b[39;00m\n\u001b[1;32m--> 136\u001b[0m logger\u001b[39m.\u001b[39minfo(\u001b[39m\"\u001b[39m\u001b[39mconn: scan_robot_ip, data:\u001b[39m\u001b[39m{0}\u001b[39;00m\u001b[39m, ip:\u001b[39m\u001b[39m{1}\u001b[39;00m\u001b[39m\"\u001b[39m\u001b[39m.\u001b[39mformat(data[:\u001b[39m-\u001b[39;49m\u001b[39m1\u001b[39;49m]\u001b[39m.\u001b[39;49mdecode(encoding\u001b[39m=\u001b[39;49m\u001b[39m'\u001b[39;49m\u001b[39mutf-8\u001b[39;49m\u001b[39m'\u001b[39;49m), ip))\n\u001b[0;32m    137\u001b[0m \u001b[39mif\u001b[39;00m ip[\u001b[39m0\u001b[39m] \u001b[39mnot\u001b[39;00m \u001b[39min\u001b[39;00m ip_list:\n\u001b[0;32m    138\u001b[0m     ip_list\u001b[39m.\u001b[39mappend(ip[\u001b[39m0\u001b[39m])\n",
      "\u001b[1;31mUnicodeDecodeError\u001b[0m: 'utf-8' codec can't decode byte 0xe7 in position 1: invalid continuation byte"
     ]
    }
   ],
   "source": [
    "from multi_robomaster import multi_robot\n",
    "\n",
    "robots_sn_list = ['3JKDH2T00159G8','3JKCJC400302GS','3JKCJC400301ZP', \n",
    "                    '3JKCJC400301UD','3JKCJC400301W0', '3JKCJC400300Y9']\n",
    "\n",
    "def sub_data_handler(sub_info):\n",
    "    pos_x, pos_y = sub_info\n",
    "    print(\"Robotic Arm: pos x:{0}, pos y:{1}\".format(pos_x, pos_y))\n",
    "\n",
    "def move(robot_group):\n",
    "    ep_arm = robot_group.robotic_arm\n",
    "\n",
    "    ep_arm.sub_position(freq=5, callback=sub_data_handler)\n",
    "\n",
    "    ep_arm.move(x=100).wait_for_completed()\n",
    "    ep_arm.move(y=-100).wait_for_completed()\n",
    "    ep_arm.move(x=-100).wait_for_completed()\n",
    "    \n",
    "    ep_arm.unsub_position()\n",
    "    \n",
    "\n",
    "multi_robots = multi_robot.MultiEP()\n",
    "multi_robots.initialize()\n",
    "\n",
    "number = multi_robots.number_id_by_sn([2, robots_sn_list[1]])\n",
    "g_red = multi_robots.build_group([2])\n",
    "\n",
    "multi_robots.run([g_red, move])\n",
    "\n",
    "multi_robots.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "ImportError",
     "evalue": "cannot import name 'multi_comm_ctrl' from 'robomaster' (c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\__init__.py)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mImportError\u001b[0m                               Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[5], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mrobomaster\u001b[39;00m \u001b[39mimport\u001b[39;00m multi_comm_ctrl\n\u001b[0;32m      3\u001b[0m multi_comm_ctrl\u001b[39m.\u001b[39mset_group(send_group, recv_group_list)\n",
      "\u001b[1;31mImportError\u001b[0m: cannot import name 'multi_comm_ctrl' from 'robomaster' (c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\__init__.py)"
     ]
    }
   ],
   "source": [
    "from robomaster import multi_comm_ctrl\n",
    "\n",
    "multi_comm_ctrl.set_group(send_group, recv_group_list)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'ep_robot' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[1], line 3\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[39m# multi_robots.close()\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m ep_robot\u001b[39m.\u001b[39mclose()\n",
      "\u001b[1;31mNameError\u001b[0m: name 'ep_robot' is not defined"
     ]
    }
   ],
   "source": [
    "# multi_robots.close()\n",
    "\n",
    "ep_robot.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "a=[[0,1],[1,2]]\n",
    "print(0.1 in range(a[0][0],a[0][1]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 1.]\n",
      " [1. 2.]\n",
      " [3. 4.]\n",
      " [1. 1.]\n",
      " [0. 0.]]\n",
      "[[0 4]\n",
      " [1 2]\n",
      " [3 4]]\n",
      "[[0]\n",
      " [1]\n",
      " [3]\n",
      " [1]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a=np.array([[0,1],[1,2],[3,4]])\n",
    "b=np.array([[1,1]])\n",
    "a=np.concatenate((a,b))\n",
    "c=np.zeros((5,2))\n",
    "\n",
    "c[:4]=a\n",
    "print(c)\n",
    "a[0]=[0,4]\n",
    "print(a[:3])\n",
    "b=a[:,:1]\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "from interval import Interval\n",
    "zoom_2_5 = Interval(2, 5)\n",
    "print(2.1 in zoom_2_5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Robotic Arm: pos x:181, pos y:0\n",
      "Robotic Arm: pos x:187, pos y:4294967270\n",
      "Robotic Arm: pos x:185, pos y:4294967243\n",
      "Robotic Arm: pos x:182, pos y:4294967231\n",
      "Robotic Arm: pos x:181, pos y:4294967229\n",
      "Robotic Arm: pos x:181, pos y:4294967229\n",
      "Robotic Arm: pos x:181, pos y:4294967229\n",
      "1.540278434753418\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "from robomaster import robot\n",
    "\n",
    "ep_robot = robot.Robot()\n",
    "ep_robot.initialize(conn_type=\"sta\")\n",
    "\n",
    "def sub_data_handler(sub_info):\n",
    "    pos_x, pos_y = sub_info\n",
    "    print(\"Robotic Arm: pos x:{0}, pos y:{1}\".format(pos_x, pos_y))\n",
    "\n",
    "ep_chassis = ep_robot.chassis\n",
    "ep_gripper=ep_robot.gripper\n",
    "ep_arm = ep_robot.robotic_arm\n",
    "ep_arm.sub_position(freq=5, callback=sub_data_handler)\n",
    "t1=time.time()\n",
    "# ep_arm.recenter().wait_for_completed()\n",
    "ep_arm.moveto(0,-70).wait_for_completed()\n",
    "t2=time.time()\n",
    "print(t2-t1)\n",
    "ep_robot.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([0.0000, 0.0667])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor(0.1000)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "a=torch.tensor([0,0.1,0.1])\n",
    "b=torch.tensor([0,0,0])\n",
    "c=torch.tensor([[0,0,0],[0,0.1,0.1]])\n",
    "print(torch.mean(c,dim=1))\n",
    "torch.max(a-b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "deque([[0, 0, 1], [0, 2, 3], [0, 0, 3]])\n",
      "0.507037878036499\n"
     ]
    }
   ],
   "source": [
    "from collections import deque\n",
    "a=[0,0,1]\n",
    "b=[0,2,3]\n",
    "c=[0,0,3]\n",
    "d=deque([a,b])\n",
    "d.extend([c])\n",
    "print(d)\n",
    "d.pop()\n",
    "len(d)\n",
    "d[0]\n",
    "d.append(time.time())\n",
    "time.sleep(0.5)\n",
    "d.append(time.time())\n",
    "print(d[-1]-d[-2])\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "t=None\n",
    "if not t:\n",
    "    print(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-271.0497, 1449.9607])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "a=[[torch.tensor([1821.7578, -284.1953]), [5.834430837314642, [-271.0496826171875, 1449.960693359375]], [116.06535210308196, [1475.4249267578125, -655.0963745117188]], \n",
    "[145.94864125305108, [1386.9503173828125, 929.1747436523438]]]]\n",
    "b=[[torch.tensor([1822.7578, -284.1953]), [6.834430837314642, [-272.0496826171875, 1448.960693359375]], [117.06535210308196, [1476.4249267578125, -656.0963745117188]], \n",
    "[146.94864125305108, [1387.9503173828125, 928.1747436523438]]]]\n",
    "torch.tensor(a[0][1][1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n"
     ]
    }
   ],
   "source": [
    "import sympy as sp\n",
    "def calc_closest_point_on_line(p,b,v):\n",
    "    global posi_target,z,field_error\n",
    "    tx,ty=sp.symbols('tx, ty')\n",
    "    s=sp.solve([(tx-b[0])/(ty-b[1])-v[0]/v[1], v[0]*(tx-p[0])+v[1]*(ty-p[1])],[tx,ty])\n",
    "    print(s[ty])\n",
    "\n",
    "calc_closest_point_on_line([3,4],[0,0],[0,1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'float'>\n",
      "0.10000000149011612\n"
     ]
    }
   ],
   "source": [
    "a=torch.Tensor([0.1])\n",
    "\n",
    "b=a.float()\n",
    "b=float(b)\n",
    "print(type(b))\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n"
     ]
    }
   ],
   "source": [
    "from interval import Interval\n",
    "x,y=1,6\n",
    "print((x and y) in Interval(5,0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(-0.4, 0)\n",
      "pose is x: -0.4000, y:0.0000, phi:0\n"
     ]
    }
   ],
   "source": [
    "from position import *\n",
    "def get_pass_posi(b, t, ready=True):\n",
    "    '''\n",
    "    b: ball position\n",
    "    t: target position\n",
    "    '''\n",
    "    x,y=sp.symbols('x, y')\n",
    "    distance=0.4 if ready else 0.31\n",
    "    solutions=sp.nonlinsolve([(x-b.x)*(b.y-t.y)-(y-b.y)*(b.x-t.x),\n",
    "                              (x-b.x)**2+(y-b.y)**2-distance**2],[x,y])\n",
    "    for s in solutions:\n",
    "        if not (s[0] in Interval(b.x, t.x) and s[1] in Interval(b.y,t.y)):\n",
    "            posi=s\n",
    "            print(s)\n",
    "    return pose(posi[0],posi[1])\n",
    "a=get_pass_posi(pose(),pose(1,0,0))\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class ps:\n",
    "    def __init__(self) -> None:\n",
    "        self.ls=[1,2,3]\n",
    "    \n",
    "    def __getitem__(self,item):\n",
    "        return self.ls[item]\n",
    "    \n",
    "p=ps()\n",
    "p[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 1.])"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "pt=torch.Tensor([0,0,0])\n",
    "np.hstack((pt[0],pt[1],1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "servo status:([0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]).\n",
      "servo status:([1, 1, 0, 0], [0, 0, 0, 0], [572, 1417, 0, 0]).\n",
      "servo status:([1, 1, 0, 0], [-56, 10, 0, 0], [572, 1417, 0, 0]).\n",
      "servo status:([1, 1, 0, 0], [-63, 30, 0, 0], [572, 1417, 0, 0]).\n",
      "servo status:([1, 1, 0, 0], [-18, 0, 0, 0], [572, 1417, 0, 0]).\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Exception in thread Thread-3:\n",
      "Traceback (most recent call last):\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\threading.py\", line 932, in _bootstrap_inner\n",
      "    self.run()\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\threading.py\", line 870, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\client.py\", line 219, in _recv_task\n",
      "    msg = self._conn.recv()\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\conn.py\", line 177, in recv\n",
      "    data, host = self._sock.recvfrom(2048)\n",
      "ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。\n",
      "Exception in thread Thread-220:\n",
      "Traceback (most recent call last):\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\threading.py\", line 932, in _bootstrap_inner\n",
      "    self.run()\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\threading.py\", line 870, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\client.py\", line 219, in _recv_task\n",
      "    msg = self._conn.recv()\n",
      "  File \"c:\\ProgramData\\anaconda3\\envs\\rmpy3.8\\lib\\site-packages\\robomaster\\conn.py\", line 177, in recv\n",
      "    data, host = self._sock.recvfrom(2048)\n",
      "ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。\n"
     ]
    }
   ],
   "source": [
    "from robomaster import robot\n",
    "import time\n",
    "ep = robot.Robot()\n",
    "ep.initialize(conn_type=\"sta\")\n",
    "\n",
    "# print(ep.servo.get_angle(0))\n",
    "# print(ep.servo.get_angle(1))\n",
    "# print(ep.servo.get_angle(2))\n",
    "# print(ep.servo.get_angle(3))\n",
    "# print(ep.servo.get_angle(4))\n",
    "\n",
    "# ep.robotic_arm.move(x=20).wait_for_completed()\n",
    "def sub_data_handler(sub_info):\n",
    "    # 完全闭合 closed, 完全张开opened, 处在中间位置normal.\n",
    "    print(\"servo status:{0}.\".format(sub_info))\n",
    "\n",
    "def sub():\n",
    "    # g.servo.moveto(index=3, angle=90)\n",
    "    ep.servo.sub_servo_info(freq=1, callback=sub_data_handler)\n",
    "    time.sleep(1)\n",
    "sub()\n",
    "time.sleep(5)\n",
    "ep.close()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([-2.0000,  0.0000,  0.5000,  0.0000,  1.0000,  0.5000,  1.0000,  2.0000,\n",
      "         0.5000])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor(3.)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "a=torch.tensor([-2,0,0.5])\n",
    "b=torch.tensor([0,1,0.5])\n",
    "c=torch.tensor([1,2,0.5])\n",
    "print(torch.concat([a,b,c]))\n",
    "torch.max(torch.concat([a-b,b-c,c-a]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x254eda90430>]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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dudx121WZ/oKcM9tVlRUFF544QVkZ2fj4MGDuPXWW/GLX/wCx44da7O9ZOuU6MWSkpLEwoULba/NZrOIiIgQGRkZbba/9957xYwZM1pNS05OFo899phD63QF9vbVunXrREBAgJOqc10AxObNm6/b5umnnxbDhg1rNW327NkiNTXVgZW5no701TfffCMAiEuXLjmlJldWXl4uAIjdu3e328adt1lX60hfcZt1RVBQkHj77bfbfE+qdarX7hkxmUzIzs5GSkqKbZpcLkdKSgqysrLanCcrK6tVewBITU1tt31v0Zm+AoDa2lr069cPWq32uknb3bnretUViYmJCA8Px2233Ya9e/dKXY4k9Ho9ACA4OLjdNly3rDrSVwC3WWazGRs3bkRdXR0mTJjQZhup1qleG0YqKipgNpuh0WhaTddoNO0ef9bpdHa17y0601fx8fFYu3YtPvvsM7z//vuwWCyYOHEiSkpKnFFyj9LeemUwGNDQ0CBRVa4pPDwca9aswSeffIJPPvkEWq0WU6dORU5OjtSlOZXFYsGSJUswadIkDB8+vN127rrNulpH+8qdt1m5ubnw9fWFSqXC448/js2bN2Po0KFttpVqneoRd+0l1zNhwoRWyXrixIkYMmQI/vWvf+H555+XsDLqyeLj4xEfH297PXHiRJw5cwavvvoq3nvvPQkrc66FCxfi6NGj2LNnj9SluLyO9pU7b7Pi4+Nx+PBh6PV6fPzxx0hLS8Pu3bvbDSRS6LV7RkJCQqBQKFBWVtZqellZGcLCwtqcJywszK72vUVn+uqnPD09MWrUKOTn5zuixB6tvfXK398fXl5eElXVcyQlJbnVerVo0SJ8/vnn+OabbxAVFXXdtu66zbrMnr76KXfaZimVSsTFxWHMmDHIyMhAQkICXnvttTbbSrVO9dowolQqMWbMGGRmZtqmWSwWZGZmtnusbMKECa3aA8COHTvabd9bdKavfspsNiM3Nxfh4eGOKrPHctf1qrscPnzYLdYrIQQWLVqEzZs34+uvv0ZsbOwN53HXdaszffVT7rzNslgsMBqNbb4n2Trl0NNjJbZx40ahUqnE+vXrxfHjx8Wjjz4qAgMDhU6nE0IIMXfuXLF06VJb+7179woPDw/x8ssvixMnTojly5cLT09PkZubK9VXcBp7+2rFihVi+/bt4syZMyI7O1vcd999Qq1Wi2PHjkn1FZympqZGHDp0SBw6dEgAEK+88oo4dOiQKCwsFEIIsXTpUjF37lxb+7Nnzwpvb2/xu9/9Tpw4cUKsXr1aKBQKsW3bNqm+gtPY21evvvqq2LJli8jLyxO5ubniySefFHK5XOzcuVOqr+A0TzzxhAgICBC7du0SpaWltkd9fb2tDbdZVp3pK3fdZi1dulTs3r1bFBQUiCNHjoilS5cKmUwmvvrqKyGE66xTvTqMCCHE66+/LqKjo4VSqRRJSUli3759tvduvvlmkZaW1qr9f/7zHzFo0CChVCrFsGHDxBdffOHkiqVjT18tWbLE1laj0Yg777xT5OTkSFC1812+/PSnj8v9k5aWJm6++eZr5klMTBRKpVL0799frFu3zul1S8HevnrxxRfFgAEDhFqtFsHBwWLq1Kni66+/lqZ4J2urnwC0Wle4zbLqTF+56zbroYceEv369RNKpVL07dtXTJs2zRZEhHCddUomhBCO3fdCRERE1L5ee84IERER9QwMI0RERCQphhEiIiKSFMMIERERSYphhIiIiCTFMEJERESSYhghIiIiSTGMEBERkaQYRoiIiEhSDCNEREQkKYYRIiIikhTDCBEREUnq/wPL03rdBEeamwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "import math\n",
    "import numpy as np\n",
    "alpha=range(0,30,20)\n",
    "l=[20*(math.tanh(i)) for i in np.linspace(0,3,20)]\n",
    "l2=[math.tanh(i) for i in np.linspace(0,1.5,20)]\n",
    "plt.figure\n",
    "plt.subplot(211)\n",
    "plt.plot(np.linspace(0,3,20),l)\n",
    "plt.subplot(212)\n",
    "plt.plot(np.linspace(0,3,20),l2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor(False)"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "a=torch.tensor(0.01)\n",
    "a>0.2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0],\n",
       "       [0, 1]])"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a=np.array([[0,0],[0,1]])\n",
    "a[0][0]=1\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 3, 1)\n",
      "[[[1.]\n",
      "  [4.]\n",
      "  [7.]]\n",
      "\n",
      " [[0.]\n",
      "  [0.]\n",
      "  [0.]]\n",
      "\n",
      " [[1.]\n",
      "  [3.]\n",
      "  [2.]]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "b=np.zeros((1,3,1))\n",
    "a=np.array([[1],[3],[2]])\n",
    "a=np.expand_dims(a,0)\n",
    "c=np.concatenate((a,b))\n",
    "c=np.concatenate((c,a))\n",
    "print(c.shape)\n",
    "c[0]=np.array([[1],[4],[7]])\n",
    "print(c)\n",
    "# plt.plot([c[i][0] for i in range(c.shape[0])])\n",
    "# np.delete(c,1,axis=0)\n",
    "# np.zeros((1,7))\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 0.5, 0.5, 0.5, 0.5, 0.5]\n",
      "[0.1, 0.1, 0.1, 0.1, 0.1]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([-1,  1,  2])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "np.concatenate([np.array([0]),np.array([0.1]*5)])\n",
    "print([1]+[0.5]*5)\n",
    "print([0.1]*5)\n",
    "a=np.array([2,0,1])\n",
    "b=np.array([1,1,0])\n",
    "np.cross(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "for i in range(4,6):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 1.]\n",
      " [1. 2.]\n",
      " [2. 3.]]\n"
     ]
    }
   ],
   "source": [
    "from position import *\n",
    "p=poses([pose(0,1),pose(1,2),pose(2,3)])\n",
    "print(p.get_arr())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "list.remove(x): x not in list",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[2], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m a\u001b[39m=\u001b[39m[\u001b[39m0\u001b[39m,\u001b[39m1\u001b[39m]\n\u001b[1;32m----> 2\u001b[0m a\u001b[39m.\u001b[39;49mremove(\u001b[39m2\u001b[39;49m)\n",
      "\u001b[1;31mValueError\u001b[0m: list.remove(x): x not in list"
     ]
    }
   ],
   "source": [
    "a=[0,1]\n",
    "a.remove(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7071067811865476"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from utils import *\n",
    "\n",
    "np.dot([1,1],[-1,1])\n",
    "trans_relative_co(pose(0,0,90), pose(1,1,0))\n",
    "p=pose(0.5,0.5,5)\n",
    "np.linalg.norm(np.array([p.x, p.y]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from position import *\n",
    "type(pose())==poses"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3, 1, 3, 1, 3, 1]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from rule_oa import *\n",
    "from position import *\n",
    "\n",
    "ps=pose(0, -0.3,180)\n",
    "pt=pose(2,0, 0)\n",
    "p1=pose(1,0,0)\n",
    "# print(next_wp_static(ps, pt, p1, speed()))\n",
    "p=poses([p1, pt,ps])\n",
    "a=np.vstack((p.get_arr()[1:,:2],p.get_arr()[0,:2]))\n",
    "[3,1]*3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 1]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "a=np.array([[0,1],[0,1]])\n",
    "b=np.array([[0,1,1],[0,1,2]])\n",
    "a=np.concatenate((np.zeros((2,1)), a), axis=1)\n",
    "np.concatenate((a,b), axis=0)\n",
    "print(b[0])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.16"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
